Skip to main content

HTTP Methods & Status Codes

Topic 8: HTTP Methods & Status Codes in Express

1. Problem Statement

Case Study: The Neighborhood Food Store Network

You manage a group of neighborhood food stores. Every day, staff and customers need to:

  • Look up what products are available.
  • Add new items to the inventory.
  • Update details about existing products.
  • Remove items that are no longer sold.

If requests get mixed up or answers are unclear, staff and customers get confused, orders are delayed, and the stores lose business.

The challenge:

How do you organize and handle these different requests so that everyone always gets the right answer, and nothing falls through the cracks?


2. Learning Objectives

By the end of this lesson, you will be able to:

  • Organize and implement all types of requests (looking up, adding, changing, removing) in Express.
  • Use and explain HTTP status codes for clear communication.
  • Add and read headers for extra information and control.
  • Write robust, RESTful endpoints for any resource.
  • Understand the difference between GET, POST, PUT, PATCH, and DELETE.
  • Know when to use each status code, and why.

3. Concept Introduction with Analogy

Analogy: The Restaurant Waiter

Imagine you’re at a restaurant:

  • You can ask the waiter for the menu (look up).
  • You can place a new order (add).
  • You can change your order (update).
  • You can cancel your order (remove).

The waiter always responds clearly:

  • “Here’s your menu.” (success)
  • “Your order is ready!” (success)
  • “Sorry, we don’t have that item.” (not found)
  • “Order cancelled.” (removed)
  • “Could you clarify your request?” (bad request)

A well-trained waiter keeps the dining experience smooth and stress-free, just as a well-designed food store system keeps requests and answers organized.

A. What Is a Request and a Response?

  • Request: When someone asks your food store system for information or to perform an action.
  • Response: The system’s answer to that request.

In web systems, these requests and responses travel over the internet using a protocol called HTTP (HyperText Transfer Protocol).

B. HTTP Methods: The Verbs of Web Requests

HTTP methods are like verbs—they tell the system what action you want to perform.

The Core Methods (CRUD)

MethodEveryday ActionSystem MeaningExample in Food Store
GET“Show me…”Retrieve/read dataList all products
POST“Add this…”Create new dataAdd a new product
PUT“Replace this…”Update/replace existing dataUpdate all details of a product
PATCH“Change this part…”Update part of existing dataChange only the price
DELETE“Remove this…”Delete dataRemove a product

Why Use Different Methods?

  • Clarity: Each method has a clear, agreed-upon meaning.
  • Safety: GET requests don’t change data; POST/PUT/PATCH/DELETE do.
  • Automation: Tools and browsers know how to handle each method.

C. HTTP Status Codes: The System’s Answers

Status codes are three-digit numbers sent with every response. They help the client (browser, app, or another system) understand what happened.

Status Code Categories

Code RangeMeaningExamples
1xxInformationalRarely used in APIs
2xxSuccess200 OK, 201 Created, 204 No Content
3xxRedirectionNot common in APIs
4xxClient Error (your fault)400 Bad Request, 404 Not Found
5xxServer Error (our fault)500 Internal Server Error

Most Important Status Codes in REST APIs

CodeWhen to UseExample Scenario
200Success (GET/PUT/PATCH)Products listed, product updated
201Resource created (POST)New product added
204Success, no content (DELETE)Product deleted, nothing to return
400Bad request (invalid input)Missing product name or price
404Not foundProduct doesn’t exist
409Conflict (rare, e.g., duplicate)Trying to add a product that already exists
500Internal server errorUnexpected bug or crash

D. HTTP Headers: Extra Info on Every Request/Response

Headers are like sticky notes attached to a package:

  • Content-Type: Tells what’s inside (e.g., JSON, HTML).

  • Authorization: Who is making the request.

  • Custom headers: E.g., X-Store-Region: "Downtown".

Example in Express:

res.setHeader("X-Store-Region", "Downtown");

E. RESTful Routing: Mapping Real Actions to System Endpoints

REST (Representational State Transfer) is a set of conventions for organizing endpoints.

  • Each resource (e.g., products) has its own route (e.g., /products).

  • The method (GET, POST, etc.) tells what action to take.

Examples:

  • GET /products → List all products

  • POST /products → Add a new product

  • GET /products/:id → Get details for one product

  • PUT /products/:id → Replace all details for a product

  • PATCH /products/:id/price → Update just the price

  • DELETE /products/:id → Remove a product

F. Error Handling and Edge Cases

  • Always check for missing or invalid data.

  • Always send a clear status code and message.

  • Never expose sensitive server errors to the client (use 500 for unexpected issues).

G. Visual Recap: How a Request Flows

H. Testing and Debugging Tips

  • Use tools like Postman or curl to send requests and see responses.

  • Always check status codes and response bodies.

  • Log requests and errors on the server for troubleshooting.

Summary Table: HTTP Methods & Status Codes

ActionMethodRouteStatus CodesUse Case
List all productsGET/products200Show all products
Get one productGET/products/:id200, 404Show product or not found
Add productPOST/products201, 400Add new product, validate input
Replace productPUT/products/:id200, 400, 404Replace all fields, validate input
Update pricePATCH/products/:id/price200, 400, 404Change price only
Remove productDELETE/products/:id204, 404Remove product, no content on success

5. Step-by-Step Data Modeling & Code Walkthrough

A. Define Product Interface and Sample Data

interface Product {
id: string;
name: string;
price: number;
inStock: boolean;
}

let products: Product[] = [
{ id: "1", name: "Bananas", price: 1.5, inStock: true },
{ id: "2", name: "Apples", price: 2.0, inStock: false },
];

B. Create Express Router and Implement RESTful Routes

import { Router, Request, Response } from "express";
const router = Router();

// GET all products
router.get("/", (req: Request, res: Response) => {
res.status(200).json(products);
});

// GET product by ID
router.get("/:id", (req: Request, res: Response) => {
const product = products.find(p => p.id === req.params.id);
if (!product) {
return res.status(404).json({ error: "Product not found" });
}
res.status(200).json(product);
});

// POST new product
router.post("/", (req: Request, res: Response) => {
const { name, price, inStock } = req.body;
if (!name || price === undefined || inStock === undefined) {
return res.status(400).json({ error: "Missing required fields" });
}
const newProduct: Product = {
id: (products.length + 1).toString(),
name,
price,
inStock,
};
products.push(newProduct);
res.status(201).json(newProduct);
});

// PUT update product
router.put("/:id", (req: Request, res: Response) => {
const productIndex = products.findIndex(p => p.id === req.params.id);
if (productIndex === -1) {
return res.status(404).json({ error: "Product not found" });
}
const { name, price, inStock } = req.body;
if (!name || price === undefined || inStock === undefined) {
return res.status(400).json({ error: "Missing required fields" });
}
products[productIndex] = { id: req.params.id, name, price, inStock };
res.status(200).json(products[productIndex]);
});

// PATCH update product price
router.patch("/:id/price", (req: Request, res: Response) => {
const product = products.find(p => p.id === req.params.id);
const { price } = req.body;
if (!product) {
return res.status(404).json({ error: "Product not found" });
}
if (typeof price !== "number" || price < 0) {
return res.status(400).json({ error: "Invalid price" });
}
product.price = price;
res.status(200).json(product);
});

// DELETE product
router.delete("/:id", (req: Request, res: Response) => {
const productIndex = products.findIndex(p => p.id === req.params.id);
if (productIndex === -1) {
return res.status(404).json({ error: "Product not found" });
}
products.splice(productIndex, 1);
res.sendStatus(204);
});

export default router;

Explanation for Each Route:

  • GET /products: Returns all products, always 200.

  • GET /products/🆔 Returns product or 404 if not found.

  • POST /products: Validates input, returns 400 if missing fields, 201 if created.

  • PUT /products/🆔 Replaces all fields, returns 400 if missing, 404 if not found, 200 if updated.

  • PATCH /products/:id/price: Only updates price, returns 400 if invalid, 404 if not found, 200 if updated.

  • DELETE /products/🆔 Removes product, 404 if not found, 204 if deleted.

6. Challenge

Your Turn!

  • Add a PATCH endpoint /products/:id/inStock to update only the inStock status of a product.

  • Return 400 Bad Request if the new status is missing or not a boolean.

7. Quick Recap & Key Takeaways

  • Use HTTP methods (GET, POST, PUT, PATCH, DELETE) to match CRUD operations.

  • Use status codes to clearly indicate success or failure.

  • Modular routes and clear responses improve reliability and user experience.

  • Always validate and structure your responses for clarity.

  • Headers can add useful metadata to responses.

8. Optional: Programmer’s Workflow Checklist

  • Use the correct HTTP method for each action.

  • Validate all input before processing.

  • Return appropriate status codes for every response.

  • Use clear, structured JSON for all responses.

  • Modularize routes for maintainability.

  • Test endpoints with tools like Postman or curl.

  • Log errors for debugging, but never leak sensitive info to clients.

  • Use headers for extra context when needed.

9. Coming up next

Learn how to type requests and responses precisely, so your API never accepts bad data or sends confusing responses!